package com.cicdi.core.util;

import com.alaya.crypto.Credentials;
import com.alaya.crypto.RawTransaction;
import com.alaya.crypto.TransactionEncoder;
import com.alaya.parameters.NetworkParameters;
import com.alaya.protocol.core.Request;
import com.alaya.protocol.core.methods.response.PlatonSendTransaction;
import com.alaya.tx.ChainId;
import com.alaya.tx.gas.GasProvider;
import com.alaya.utils.Convert;
import com.alaya.utils.Numeric;
import com.cicdi.core.service.FastHttpService;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;

/**
 * 发送交易的工具
 *
 * @author renhui
 * @date 2020/6/30
 */

public class SendUtil {
    protected final FastHttpService web3jService;

    public SendUtil(String url) {
        //初始化 web3j service 对象
        web3jService = new FastHttpService(url);
    }

    /**
     * 从from地址发送交易到目的地址
     *
     * @param from        源地址
     * @param toAddresses 目标地址
     * @param atpValue    交易金额，单位为atp
     */
    public void fastSend(Credentials from, List<String> toAddresses, BigDecimal atpValue) throws IOException {
        long nonce = NonceUtil.getNonce(this.web3jService, from).longValue();
        for (String toAddress : toAddresses) {
            fastSend(from, nonce++, atpValue, toAddress, "", Common.MID_GAS_PROVIDER);
        }
    }

    /**
     * 快速发送交易，并发操作。
     *
     * @param credentials 钱包
     * @param nonce       nonce值
     * @param atpValue    发送金额，单位为atp
     * @param to          目标地址
     * @param data        数据
     * @param gasProvider gas配置
     */
    public void fastSend(Credentials credentials, long nonce, BigDecimal atpValue, String to, String data, GasProvider gasProvider) {
        BigDecimal weiValue = Convert.toVon(atpValue, Convert.Unit.ATP);
        Common.executor.execute(() -> {
            try {
                RawTransaction rawTransaction = RawTransaction.createTransaction(
                        BigInteger.valueOf(nonce),
                        gasProvider.getGasPrice(),
                        gasProvider.getGasLimit(),
                        to,
                        weiValue.toBigIntegerExact(),
                        Numeric.cleanHexPrefix(data));
                fastSignAndSend(rawTransaction, credentials);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 快速对交易签名并发送
     *
     * @param rawTransaction 交易
     * @param credentials    钱包
     * @throws IOException io流异常
     */
    public void fastSignAndSend(RawTransaction rawTransaction, Credentials credentials) throws IOException {
        byte[] signedMessage;

        if (NetworkParameters.CurrentNetwork.getChainId() > ChainId.NONE) {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, NetworkParameters.CurrentNetwork.getChainId(), credentials);
        } else {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        }

        String hexValue = Numeric.toHexString(signedMessage);
        Request<String, PlatonSendTransaction> request = new Request<>(
                "platon_sendRawTransaction",
                Collections.singletonList(hexValue),
                web3jService,
                PlatonSendTransaction.class);
        web3jService.fastSend(request);
    }
}
